package plgcore

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/utils"
	"dgo/plg/plgnet"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"time"
)

type ExPlg struct {
	PlgBase
	dispflag  int8
	innerImpl *utils.Subscribe
	msglst    *utils.SyncCycleList
}

/*
		{
		  "id": "xxx",
		  "type": "core.ex",
		  "conf": {
	          "dispflag":0
		  }
		}

// dispflag

		0: 响应时按照队订阅id排队进行回调
	    1: 响应时直接调用回调
*/
func (this *ExPlg) ReloadConf(conf *wrapper.SuperValue) error {
	if conf == nil {
		return nil
	}

	if this.innerImpl == nil {
		this.innerImpl = utils.NewSubscribe()
	}

	if this.msglst == nil {
		this.msglst = utils.NewSyncCycleList()
	}

	this.dispflag = conf.Int8ByName("dispflag", 0)

	utils.DefaultPatrolTask().AddTask(this, time.Second*30, func(id interface{}, args ...interface{}) {
		//utils.DefaultWorkers().PostTaskFunc(this, this.innerWork)
	})
	return nil
}

func (this *ExPlg) Close() (err error) {
	this.PlgBase.Close()
	utils.DefaultPatrolTask().DelTask(this)

	return
}

func (this *ExPlg) id2str(id interface{}) string {
	if str, ok := id.(string); ok {
		return str
	}
	str := fmt.Sprintf("%p", id)
	return str
}

func (this *ExPlg) Sub(id, topic string, cb func(id, topic string, args ...interface{}) (ok bool)) {
	this.innerImpl.Sub(id, topic, func(id, topic string, args ...interface{}) (ok bool) {
		if this.dispflag == 0 {
			return utils.DefaultWorkers().PostTaskFunc(id, func() {
				cb(id, topic, args...)
			}) == nil
		} else {
			return cb(id, topic, args...)
		}
	})

}

func (this *ExPlg) Unsub(id, topic string) bool {
	return this.innerImpl.Unsub(id, topic)
}

func (this *ExPlg) Pub(topic string, max int, args ...interface{}) int {
	return this.innerImpl.Pub(topic, max, args...)
}

func (this *ExPlg) SubscribeChannelEx(channelid string, id interface{}, onInput utils.SubscribeCallback) (subtopic string, err error) {
	isBreak := false
	this.innerImpl.Sub(this.id2str(id), channelid, func(id, topic string, args ...interface{}) (ok bool) {
		if this.dispflag == 0 {
			return utils.DefaultWorkers().PostTaskFunc(id, func() {
				onInput(utils.GetIdxValFromVars(args, 1), topic, id, utils.GetIdxValFromVars(args, 0), utils.GetIdxValFromVars(args, 2), &isBreak)
			}) == nil
		} else {
			onInput(utils.GetIdxValFromVars(args, 1), topic, id, utils.GetIdxValFromVars(args, 0), utils.GetIdxValFromVars(args, 2), &isBreak)
			return true
		}
	})
	return channelid, nil
}

func (this *ExPlg) SubscribeChannel(channelid string, id interface{}, onInput utils.SubscribeCallback) {
	isBreak := false
	this.innerImpl.Sub(this.id2str(id), channelid, func(id, topic string, args ...interface{}) (ok bool) {
		if this.dispflag == 0 {
			return utils.DefaultWorkers().PostTaskFunc(id, func() {
				onInput(utils.GetIdxValFromVars(args, 1), topic, id, utils.GetIdxValFromVars(args, 0), utils.GetIdxValFromVars(args, 2), &isBreak)
			}) == nil
		} else {
			onInput(utils.GetIdxValFromVars(args, 1), topic, id, utils.GetIdxValFromVars(args, 0), utils.GetIdxValFromVars(args, 2), &isBreak)
			return true
		}
	})
}

func (this *ExPlg) UnsubscribeChannel(channelid string, id interface{}) bool {
	return this.innerImpl.Unsub(this.id2str(id), channelid)
}

func (this *ExPlg) DispatchData(channelid string, sender interface{}, data interface{}, tag interface{}) (err error) {
	this.innerImpl.Pub(channelid, 0, data, sender, tag)
	return nil
}

func (this *ExPlg) OnHttpStatus(rec *plgnet.PlgHttpRec) (rval interface{}, errcode int, err error) {
	itype := rec.QryAsInt("type", 0)
	if itype == 99 {
		json := wrapper.NewSVObject()
		json.SetKeyValues("now", utils.NowString())
		json.SetKeyValue("status", this.innerImpl.Status())
		if rec.QryAsInt("json", 0) == 1 {
			PrjHttpUtils.ResponseAsJSON(rec.RespW, json.AsJSONStringEx(false, true))
		} else {
			PrjHttpUtils.JSON2TableRec(rec.RespW, "", json.AsJSONString(false))
		}
	} else if itype == 98 {
		rec.ResponseSyncListNEx(this.msglst)
	} else if itype == 1 {
		json := wrapper.NewSVArray()
		//searchval := rec.QryAsString("searchval", "")
		//sn := 0
		//maxn := rec.QryAsInt("n", 100)
		//this.lst.ListRangeV2(func(key, val interface{}) bool {
		//	pojo := val.(*VrsSitePojo)
		//	ok := true
		//	if len(searchval) > 0 {
		//		ok = strings.Contains(pojo.id, searchval)
		//	}
		//	return ok
		//}, func(k0, v0, k1, v1 interface{}) bool {
		//	p0 := v0.(*VrsSitePojo)
		//	p1 := v1.(*VrsSitePojo)
		//	return p0.id < p1.id
		//}, func(key, val interface{}) bool {
		//	sn++
		//	pojo := val.(*VrsSitePojo)
		//	itm := json.AppendObject()
		//	itm.SetKeyValue("sn", sn)
		//	itm.SetKeyValue("id", pojo.id)
		//	return sn < maxn
		//})

		if rec.QryAsInt("json", 0) == 1 {
			PrjHttpUtils.ResponseAsJSON(rec.RespW, json.AsJSONStringEx(false, false))
		} else {
			PrjHttpUtils.JSON2Table(rec.RespW, "", json.AsJSONString(false))
		}
	} else if itype == 2 {
		rec.ResponseText(this.innerImpl.StatusDetail())
	} else {
		var sb utils.BytesBuilder
		PrjHttpUtils.AppendIndexBody(&sb, "status", "status?type=99")
		PrjHttpUtils.AppendIndexBody(&sb, "msglist", "status?type=98&n=100&searchval=")
		//PrjHttpUtils.AppendIndexBody(&sb, "lst", "status?type=1&n=100&searchval=")
		PrjHttpUtils.AppendIndexBody(&sb, "details", "status?type=2")
		PrjHttpUtils.ResponseBodyHtml(rec.RespW, sb.String())
	}
	return
}

func (this *ExPlg) LogInfoMessage(s string, args ...interface{}) {
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_INFO, 1, s, args...)
}

func (this *ExPlg) LogWarnMessage(s string, args ...interface{}) {
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_WARN, 1, s, args...)
}

func CreateExPlgFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ExPlg{}

	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}
